/*
 * PerformanceController
 *
 * Copyright (c) 2018 Manulife International Ltd.
 *
 * Description:
 *
 * Maintenance History
 *
 * YYMMDD  Who              Reason
 * ======= ================ ====================================================
 * 180209  Eric Zhang        Application development
 *
 */
package com.manulife.hk.performance.exception;

import com.manulife.hk.performance.response.ApiError;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import static org.springframework.http.HttpStatus.*;

import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

	@Override
	public ResponseEntity<Object> handleBindException(BindException exception, HttpHeaders headers, HttpStatus status,
			WebRequest request) {
		logger.debug("Validation exceptions: {}", exception);
		String errorMsg = exception.getBindingResult().getFieldErrors().stream()
				.map(x -> x.getField() + " " + x.getDefaultMessage()).collect(Collectors.joining(","));
		ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST);
		apiError.setMessage(errorMsg);
		return buildResponseEntity(apiError);
	}

	/**
	 * Handles EntityNotFoundException. Created to encapsulate errors with more
	 * detail than javax.persistence.EntityNotFoundException.
	 *
	 * @param ex
	 *            the EntityNotFoundException
	 * @return the ApiError object
	 */
	@ExceptionHandler(EntityNotFoundException.class)
	protected ResponseEntity<Object> handleEntityNotFound(EntityNotFoundException ex) {
		logger.error("EntityNotFoundException occurs: {}", ex);
		ApiError apiError = new ApiError(NOT_FOUND);
		apiError.setMessage(ex.getMessage());
		return buildResponseEntity(apiError);
	}

	@Override
	protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
			HttpHeaders headers, HttpStatus status, WebRequest request) {
		logger.debug("Validation exceptions: {}", ex);
		String errorMsg = ex.getBindingResult().getFieldErrors().stream()
				.map(x -> x.getField() + " " + x.getDefaultMessage()).collect(Collectors.joining(","));
		ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST);
		apiError.setMessage(errorMsg);
		return buildResponseEntity(apiError);
	}

	@ExceptionHandler(Exception.class)
	protected ResponseEntity<Object> handleParameterValidationException(Exception ex, WebRequest request) {
		logger.error("Exception occurs: {}", ex);
		ApiError apiError = new ApiError(INTERNAL_SERVER_ERROR);
		apiError.setMessage(ex.getMessage());
		return buildResponseEntity(apiError);
	}

	private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
		return new ResponseEntity<>(apiError, apiError.getStatus());
	}

}
